package com.gopay.common.util.pwd;

import com.gopay.common.constants.microdone.PwdCtrlFingerTypeConstants;
import com.gopay.common.util.HttpClientUtil;
import com.gopay.common.vo.PwdCtrlFingerVerifyResultVO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * 键盘芭蕾接口工具类
 * @author yu_liu6@hnair.com
 * @date 2018-05-22 19:06:47
 */
public class PwdCtrlFingerUtil {

    private static String PASS = "1";

    private static String FAILURE = "2";

    private static int REG_FINGER_COUNT = 5;

    private static Integer TIME_OUT = 2000;

    /** logger */
    private static final Logger LOGGER = LoggerFactory.getLogger(PwdCtrlFingerUtil.class);

    /**
     * 键盘芭蕾建模接口
     * @param authUrl 键盘芭蕾认证服务器地址
     * @param param 键盘芭蕾建模参数
     * @return
     */
    public static PwdCtrlFingerVerifyResultVO registFinger(String authUrl, Map<String, String> param){
        final String regSuccess = "3";
        param.put("action", PwdCtrlFingerTypeConstants.PD_REG);
        LOGGER.info("【键盘芭蕾-建模】服务器地址：{}, 用户名：{}", authUrl, param.get("user_name"));
        try {
            String resultXml = HttpClientUtil.postByBuilder(authUrl, param, TIME_OUT);
            if(StringUtils.isBlank(resultXml)){
                LOGGER.error("【键盘芭蕾-建模】服务器返回结果为空");
                return null;
            }
            PwdCtrlFingerVerifyResultVO resultVO = new PwdCtrlFingerVerifyResultVO();
            resultVO.setAppType(param.get("app_type"));
            resultVO.setUserName(param.get("user_name"));
            resultVO.setPwdResultHash(param.get("pwdResultHash"));
            resultVO.setUserFinger(param.get("user_finger"));
            resultVO.setRandomNum(param.get("random_num"));
            resultVO.setActionType(PwdCtrlFingerTypeConstants.PD_REG);
            boolean isUpToMaxCount = false;
            String regCountStr = getNodeText(resultXml, "fingerdate_length");
            String msg = "";
            if(StringUtils.isNotBlank(regCountStr)){
                int regCount = Integer.parseInt(regCountStr);
                isUpToMaxCount = regCount >= REG_FINGER_COUNT;
                msg = "建模中/还需" + (REG_FINGER_COUNT - regCount) + "条有效记录";
            }
            String auth1Code = getNodeText(resultXml, "auth1");
            resultVO.setRegSuccess(!FAILURE.equals(auth1Code) && (regSuccess.equals(auth1Code) || isUpToMaxCount));
            resultVO.setVerifySuccess(PASS.equals(auth1Code));
            //目前微通仅支持成功/失败展示，1-通过，2-失败，3-建模成功
            resultVO.setResult(resultVO.isRegSuccess() ? "建模成功" : resultVO.isVerifySuccess() ? msg : "建模失败，清除异常数据");
            resultVO.setCode(resultVO.isRegSuccess() ? "建模成功" : resultVO.isVerifySuccess() ? msg : "建模失败，清除异常数据");
            LOGGER.info("【键盘芭蕾-建模】结果：{}", resultVO);
            return resultVO;
        } catch (Exception e) {
            LOGGER.error("【键盘芭蕾-建模】失败", e);
        }
        return null;
    }

    /**
     * 键盘芭蕾认证接口
     * @param authUrl 键盘芭蕾认证服务器地址
     * @param param 键盘芭蕾认证参数
     * @return
     */
    public static PwdCtrlFingerVerifyResultVO verifyFinger(String authUrl, Map<String, String> param){
        param.put("action", PwdCtrlFingerTypeConstants.PD_AUTH);
        LOGGER.info("【键盘芭蕾-认证】服务器地址：{}, 用户名：{}", authUrl, param.get("user_name"));
        try {
            String resultXml = HttpClientUtil.postByBuilder(authUrl, param, TIME_OUT);
            if(StringUtils.isBlank(resultXml)){
                LOGGER.error("【键盘芭蕾-认证】服务器返回结果为空");
                return null;
            }
            PwdCtrlFingerVerifyResultVO resultVO = new PwdCtrlFingerVerifyResultVO();
            resultVO.setAppType(param.get("app_type"));
            resultVO.setUserName(param.get("user_name"));
            resultVO.setPwdResultHash(param.get("pwdResultHash"));
            resultVO.setUserFinger(param.get("user_finger"));
            resultVO.setRandomNum(param.get("random_num"));
            resultVO.setActionType(PwdCtrlFingerTypeConstants.PD_AUTH);
            String auth1Code = getNodeText(resultXml, "auth1");
            //默认进行认证的都是注册成功的用户
            resultVO.setRegSuccess(true);
            resultVO.setVerifySuccess(PASS.equals(auth1Code));
            String similarity = getNodeText(resultXml, "auth2");
            resultVO.setSimilarity(similarity);
            resultVO.setSimilarityMin(getNodeText(resultXml, "user_finger_min"));
            //目前微通仅支持成功/失败展示，1-通过，2-失败，3-建模成功
            StringBuilder msg = new StringBuilder();
            msg.append("本次")
                    .append(similarity)
                    .append("/最小允许")
                    .append(resultVO.getSimilarityMin())
                    .append(resultVO.isVerifySuccess() ? "/认证成功" : "/认证失败");
            resultVO.setResult(msg.toString());
            resultVO.setCode(msg.toString());
            LOGGER.info("【键盘芭蕾-认证】结果：{}", resultVO);
            return resultVO;
        } catch (Exception e) {
            LOGGER.error("【键盘芭蕾-认证】失败", e);
        }
        return null;
    }

    /**
     * 重置用户相似度最小值
     * @param authUrl 键盘芭蕾认证服务器地址
     * @param userName 键盘芭蕾用户名
     * @return
     */
    public static boolean resetUserSimilarityMin(String authUrl, String userName, String similarityMin){
        Map<String, String> param = new HashMap<>(4, 1);
        param.put("action", PwdCtrlFingerTypeConstants.PD_SET_DATA);
        param.put("user_name", userName);
        param.put("set_data", similarityMin);
        LOGGER.info("【键盘芭蕾-重置相似度最小值】服务器地址：{}, 传入参数：{}", authUrl, param);
        try {
            String resultXml = HttpClientUtil.postByBuilder(authUrl, param, TIME_OUT);
            final String noRegUser = "0";
            boolean isSuccess = !noRegUser.equals(getNodeText(resultXml, "set_data"));
            LOGGER.info("【键盘芭蕾-重置相似度最小值】结果：{}", isSuccess);
            return isSuccess;
        } catch (Exception e) {
            LOGGER.error("【键盘芭蕾-设置用户相似度最小值】失败", e);
        }
        return false;
    }

    /**
     * 重置用户习惯
     * @param authUrl 键盘芭蕾认证服务器地址
     * @param userName 键盘芭蕾用户名
     * @return
     */
    public static boolean resetUserInfo(String authUrl, String userName){
        Map<String, String> param = new HashMap<>(4);
        param.put("action", PwdCtrlFingerTypeConstants.PD_DELETE_DATA);
        param.put("user_name", userName);
        LOGGER.info("【键盘芭蕾-重置用户习惯】服务器地址：{}, 传入参数：{}", authUrl, param);
        try {
            String resultXml = HttpClientUtil.postByBuilder(authUrl, param, TIME_OUT);
            boolean isSuccess = PASS.equals(getNodeText(resultXml, "flag"));
            LOGGER.info("【键盘芭蕾-重置用户习惯】结果：{}", isSuccess ? "重置成功" : "无此注册用户");
            return true;
        } catch (Exception e) {
            LOGGER.error("【键盘芭蕾-重置用户习惯】失败", e);
            return false;
        }
    }

    /**
     * 查询注册用户
     * @param authUrl 键盘芭蕾认证服务器地址
     * @param userName 键盘芭蕾用户名
     * @return
     */
    public static boolean checkUser(String authUrl, String userName){
        Map<String, String> param = new HashMap<>(4);
        param.put("action", PwdCtrlFingerTypeConstants.PD_CHECK);
        param.put("user_name", userName);
        LOGGER.info("【键盘芭蕾-查询注册用户】服务器地址：{}, 传入参数：{}", authUrl, param);
        try {
            String resultXml = HttpClientUtil.postByBuilder(authUrl, param, TIME_OUT);
            boolean isSuccess = PASS.equals(getNodeText(resultXml, "user_name"));
            LOGGER.info("【键盘芭蕾-查询注册用户】结果：{}", isSuccess);
            return isSuccess;
        } catch (Exception e) {
            LOGGER.error("【键盘芭蕾-查询注册用户】失败", e);
        }
        return false;
    }

    /**
     * 获取xml节点的值
     *
     * @param xmlString
     * @param nodeName
     * @return
     */
    private static String getNodeText(String xmlString, String nodeName) {
        String beginName = "<" + nodeName + ">";
        String endName = "</" + nodeName + ">";
        int beginIndex = xmlString.indexOf(beginName);
        if (beginIndex == -1) {
            return "";
        }
        int endIndex = xmlString.indexOf(endName);
        if (endIndex == -1) {
            return "";
        }
        return xmlString.substring(beginIndex + beginName.length(), endIndex);
    }
}
